/*
* $Id: Database.cpp 2 2009-12-23 13:58:02Z volok-aleksej@yandex.ru $
*
* Copyright 2008-2009 by Volokitin Alexey
* All rights reserved
*
*/
#include "Common/include.h"
#include "Database.h"
#include <sqlite3.h>

#if defined(_UNICODE)
#define sqlite_open sqlite3_open16
#define sqlite_prepare sqlite3_prepare16_v2
#define sqlite_errmsg sqlite3_errmsg16
#else
#define sqlite_open sqlite3_open
#define sqlite_prepare sqlite3_prepare_v2
#define sqlite_errmsg sqlite3_errmsg
#endif/*defined(_UNICODE)*/

#define ERROR_SQLITE(database) CSQLiteError(_T(__FILE__), _T(__FUNCTION__), __LINE__, database)

CSQLiteError::CSQLiteError(const std::tstring& strFileName, const std::tstring& strFunction, int nLine, void* database)
: CBaseError(strFileName, strFunction, nLine, (TCHAR*)sqlite_errmsg((sqlite3*)database)) {}

CDatabase::CDatabase(const std::tstring& strDatabaseName){
	m_strDatabaseName = strDatabaseName;
	m_bOpen = false;
	m_pDatabase = NULL;
}
CDatabase::~CDatabase(){
	if(m_pDatabase)
		sqlite3_close(m_pDatabase);
}
MyTable CDatabase::ExecRequest(const std::tstring& strSqlRequest){
	sqlite3_stmt* sqlStmt;
	TCHAR* strTail;
	MyTable aTable;
 	TRY
		if(sqlite_prepare(m_pDatabase, strSqlRequest.c_str(), (int)(strSqlRequest.size()*sizeof(TCHAR)), &sqlStmt, (const void**)&strTail) != SQLITE_OK){
			throw ERROR_SQLITE(m_pDatabase); }
		int res = sqlite3_step(sqlStmt);
		if(res != SQLITE_DONE && res != SQLITE_ROW){
			throw ERROR_SQLITE(m_pDatabase); }
		while (res == SQLITE_ROW)		{
			int nColumn = sqlite3_data_count(sqlStmt);
			if(nColumn == 0)
				break;
			std::vector<CTableItem> aTableItems;
			for (int i = 0; i < nColumn; i++){
				CTableItem table;
				TCHAR* pValue = (TCHAR*)sqlite3_column_text16(sqlStmt, i);
				if(pValue)
					table.m_strValueColumn = pValue;
				TCHAR* pName = (TCHAR*)sqlite3_column_origin_name16(sqlStmt, i);
				if(pName)
					table.m_strNameColumn = pName;
				aTableItems.push_back(table);
			}
			aTable.push_back(aTableItems);
			res = sqlite3_step(sqlStmt);
		}
	CATCH
		AfxMessageBox(error.GetError().c_str());
	END_TRY_CATCH
	sqlite3_reset(sqlStmt);
	sqlite3_finalize(sqlStmt);
	return aTable;
}
bool CDatabase::IsExistTable(const std::tstring& strTableName){
	MyTable table = ExecRequest(_T("SELECT tbl_name FROM sqlite_master;"));
	if(table.empty())
		return FALSE;
	for(MyTable::iterator it = table.begin(); it != table.end(); it++){
		if(strTableName == (*it)[0].m_strValueColumn)
			return TRUE;
	}
	return FALSE;
}
void CDatabase::BeginTransaction(const std::tstring& strNameTransaction){
	std::tstring strSqlRequest = _T("BEGIN TRANSACTION ");
	strSqlRequest = strSqlRequest + _T("\'") + strNameTransaction + _T("\';");
	ExecRequest(strSqlRequest);
}
void CDatabase::EndTransaction(const std::tstring& strNameTransaction){
	std::tstring strSqlRequest = _T("END TRANSACTION ");
	strSqlRequest = strSqlRequest + _T("\'") + strNameTransaction + _T("\';");
	ExecRequest(strSqlRequest);
}
bool CDatabase::IsOpen(){
	return m_bOpen;
}
void CDatabase::Open(){
	if(!m_bOpen){
		if(sqlite_open(m_strDatabaseName.c_str(), &m_pDatabase) != SQLITE_OK)
			AfxMessageBox((TCHAR*)sqlite_errmsg(m_pDatabase));
		else
			m_bOpen = true;
	}
}
std::tstring CDatabase::GetDatabaseName(){
	return m_strDatabaseName;
}
void CDatabase::Free(){
	delete this;
}